package compound.repository.entries

/**
 * a simple compound
 */
class Compound {

  /**
   * makes this class use the searchable context
   */
  static searchable = {
    synonyms component: true
    dbLinks component: true
    smiles component: true
    iupac component: true
    inchiHashKey component: true
  }

  Date dateCreated

  Date lastUpdated

  static hasMany = [
          synonyms: Synonym,
          dbLinks: DBLinks,
          smiles: Smiles,
          iupac: IUPAC
  ]

  static mapping = {
    version false // Required to avoid stale object exceptions when hibernate attempts a lock
    synonyms batchSize: 30
    smiles batchSize: 2
    iupac batchSize: 5
    dbLinks batchSize: 20
  }

  /*
static fetchMode = {
synonyms: 'eager'
smiles: 'eager'
iupac: 'eager'
dbLinks: 'eager'
}
  */

  static constraints = {
    inchi(maxSize: 15000, nullable: false, unique: true)
    formula(maxSize: 5000, nullable: true)
    exactMolareMass(nullable: true)
  }

  static indexes = {
    inchiIndex('inchi')
    formulaIndex('formula')
  }

  static belongsTo = InchiHashKey

  InchiHashKey inchiHashKey

  String inchi

  String formula

  double exactMolareMass

  String toString() {
    return "Compound: ${id} - ${inchi}"
  }


  def getDefaultName() {

    if (synonyms == null) {
      return "Unknown"
    }
    if (synonyms.size() > 0) {
      return getFilteredSynonyms()[0].name
    }
    else {
      return "Unknown"
    }
  }

  /**
   * removes duplicatesd synonym, which can be written small and large sometimes. It also removes flagged synonyms. It also sorts the list by rating
   *
   * @return
   */
  def getFilteredSynonyms() {
    List<Synonym> syn = new ArrayList<Synonym>()

    Set<String> index = new HashSet<String>()

    for (Synonym s: synonyms) {
      if (s.flagged == false || s.flagged == null) {

        if (index.contains(s.getName().toLowerCase()) == false) {
          index.add(s.getName().toLowerCase())
          syn.add(s)
        }
      }
    }

    syn.sort {Synonym a, Synonym b -> b.rating.compareTo(a.rating)}

    return syn
  }

}
